[React] よーし! いっちょReactやってみっか! #4 書いてみよう編
はじめに
CX事業本部の中安です。まいどです。
モバイルアプリエンジニアな自分がReact
を始めてみることにした
「よーし! いっちょReactやってみっか!」シリーズの続きです。
今回もよろしくお願いします。
前回はReact
でよく使われる基本キーワードをまとめてみました。
今回からは実際にReact
のソースコードを書いていってみましょう。
HTMLファイルで書いてみよう
初回のブログでは、npx
コマンドを使ってReact
プロジェクトを作り、それを起動することでブラウザでWEBアプリを確認することができました。
では、そういう形でないとReact
は使えないのかというと、そうではないです。
1つのシンプルなHTML
ファイルだけでもReact
は利用可能です。
それでは、基本を習得すべくHTML
ファイルを使ってReact
のソースコードへの実装を体感してみたいと思います。
ベースのHTML
今回index.html
ファイルを作り、以下のようなHTML
をベースとして用意しました。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> </head> <body> </body> </html>
なんの変哲もないHTML
ですね。
ブラウザで開いてみても真っ白なページだと思います。(タイトルは設定されていますが)
CDNリンクを使う
React
ここにReact
を使用する場合は、react
とreact-dom
という2つのライブラリを読み込むことが必要です。
その読み込み方法としてCDNリンクを使うことができます。
開発用としてのdevelopment.js
と、本番用のmin.js
が用意されていますが、
今回はdevelopment.js
を使うこととします。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> </head> <body> </body> </html>
ハイライトされている<script>
が変更した箇所です。@16
とされているところは現時点のバージョンなので、この記事が古くなっていたら差し替わる可能性があります。バージョンを特定する時なども適宜書き換えてください。
最新のバージョンやcrossorigin
属性の必要性などはこちらを参考ください。
Babel
JSX
の利用にはBabel
が必要であることは前回書きました。こちらもCDNリンクで読み込みます。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script> </head> <body> </body> </html>
こちらも開発用としてのbrowser.js
と、本番用のbrowser.min.js
が用意されているようですね。
Body部の追記
<body>
内にアプリケーションの基礎部分を書いていきましょう。
np script タグ
JavaScript
が実行されない環境への対応のため<noscript>
タグを埋め込みます。
内容は各自お任せしますが、今回は以下のように書きます。
<noscript>You need to enable JavaScript to run this app.</noscript>
ルートタグ
React
の場合、HTML
にUI要素をいくつも書き連ねるという手段は取りません。その役割はJavaScript
が行います。
ではHTML
の方はどうするかというと、ルートタグとしてひとつの<div>
タグを用意するのがセオリーのようです。
この<div>
の中をDOM
操作によって差し替える形でアプリケーションは動いていくわけですね。
ですので、以下のタグを<body>
の中に配置します。
<div id="root"></div>
ここまでのHTML
あらためて上記2つを実装した形が以下のようになります。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> </body> </html>
scriptタグでReactを使う
ここでいよいよReact
を使った実装をしていこうと思います。
まずは、スクリプトを書いていくために<script>
タグを用意するのですが、前回のブログのBabel
の項にも書いたとおりタイプ指定が必要になります。
JSX
が使えるようにするためには<script type="text/babel">
と指定してください。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <script type="text/babel"> // あとで書く </script> </body> </html>
HTML
の準備はこんなものなので、ここからはスクリプトだけに注視しましょう。
以降はこの<script type="text/babel">
内の実装になります。
ルートタグを取得
先程用意したルートタグをスクリプト側で取得するようにします。
この取得はJavaScript
元来の標準機能を使用します。
ネット上ではgetElementById
を使うパターンとquerySelector
を使うパターンが見受けられますが、
公式のチュートリアルではgetElementById
を使っているようなのでこちらを採用しますね。
let dom = document.getElementById('root');
両者の違いはこのあたりを参考ください。
ReactDOM
取得したルートタグDOMに対して作成したコンポーネントをレンダリングしていくことがReact
の基本的な流れになります。
いかに色々コンポーネントを組み合わせても、この作業がなければ画面は真っ白のままです。
このレンダリングの作業を行うのがReactDOM
という登場人物で、このReactDOM
のrender
メソッドを呼び出すことで描画が実行されます。
ReactDOM.render()
のシグネチャはこのような形です。
ReactDOM.render(描画する内容, 描画する先, [コールバック]);
では、試しに使ってみます。
let dom = document.getElementById('root'); ReactDOM.render( <h1>Hello World!</h1>, dom);
改行していて読みにくければすいません。
描画する内容(第1引数)にはJSX
構文を、描画する先(第2引数)にはルートタグdom
を指定しています。
通常のHTML
を書く時も当然気をつけなければなりませんが、
JSX
の場合は閉じタグなどが抜けているとシンタックス(構文)エラーが吐き出されます。
閉じ忘れたりすると、ブラウザがよしなに解釈してくれるわけもなく(そもそもブラウザを通過してない)、真っ白になりますので注意しましょう。
さて、ブラウザで再読み込みをしてみると大きく「Hello World!」が表示されると思います。
おめでとう。これで僕もReact
使いだ!
コンポーネントを使う
ただ、まぁこれだけだと何もReact
っぽくないですね。
色々とやりたいところですがReact
の特長である「コンポーネント」を使ってみましょう。
関数コンポーネント"Hello"
先程「Hello World!」を表示していた<h1>
要素をコンポーネント化してみます。
名前は適当に「Hello」という関数コンポーネントにします。
ソースコードを以下のように書き換えます。
const Hello = (props) => { return <h1>Hello World!</h1> } let dom = document.getElementById('root'); ReactDOM.render( <Hello />, dom);
ブラウザをリロードしてみても「Hello World!」の表示は変わらず表示されると思います。 まずはコンポーネント化に成功しました。
※「何だ? この Hello = (props) => {}
って書き方は?」ってなった方は前回のブログの「関数コンポーネント」の項を参考ください。
値を書き換える
props
の仕組みを使って外部からコンポーネント内の表示内容を変更できるようにしてみます。
props
はコンポーネントの属性に与えられた値がオブジェクトとなって渡されるという仕組みでした。
まずは、引き取る側のコンポーネントの改修です。
const Hello = (props) => { return <h1>Hello {props.name}!</h1> }
このように{}
括弧(ブレス)で囲った箇所は変数がバインドされるようになります。
props
のname
という値が入ることになります。
この時点でブラウザをリロードしてみると「Hello !」という表示になると思います。
name
が与えられなくても特にエラーが生じるわけではないようです。
では、渡す側の改修もします。
let dom = document.getElementById('root'); ReactDOM.render( <Hello name="Developers.IO" />, dom);
Hello
コンポーネントの属性値にname
を与えました。
すると、ブラウザのリロードで「Hello Developers.IO!」という表示になると思います。
すごく簡単な例ですが、props
の使い方が分かりましたね。
JSXの注意点
調子に乗ってレンダリングの箇所にもう1個コンポーネントをこんな感じに表示させたくなりました。
let dom = document.getElementById('root'); ReactDOM.render( <Hello name="Developers.IO" /><Hello name="Classmethod" />, dom);
こうすれば 「Hello Developers.IO! Hello Classmethod!」 と表示されるはず・・・。
しかし、これはエラーが生じてしまいます。残念。
JSX
構文としては複数のエレメントを並列に置いて返すことができないのです。
複数エレメントのコンポーネントを作る際には、<div>
タグなどで囲って1つのDOM
になるように指定するよう注意することが必要ですね。
let dom = document.getElementById('root'); ReactDOM.render( <div> <Hello name="Developers.IO" /> <Hello name="Classmethod" /> </div>, dom);
これで 「Hello Developers.IO! Hello Classmethod!」 と表示されると思います。
ここまでのソースコード
とりあえずコピペで動くと思いますが、写経が大事ですよっ (CDNはコピーでいいですけど)
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Reactのテスト</title> <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.38/browser.js"></script> </head> <body> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <script type="text/babel"> const Hello = (props) => { return <h1>Hello {props.name}!</h1> } let dom = document.getElementById('root'); ReactDOM.render( <div> <Hello name="Developers.IO" /> <Hello name="Classmethod" /> </div>, dom); </script> </body> </html>
最後に
ここまでで単独のHTMLファイルでReact
を使う環境を作り、
コンポーネントを作って、属性値を渡すところまでを実際にソースコードに落としてみました。
まだまだ初級編って感じが続くかと思いますが、どうぞお付き合いください。
では、またー。